package com.photoeditor.demo.util.update;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.text.TextUtils;

import com.common.base.ComponentContext;
import com.common.base.app.BaseApplication;
import com.common.base.log.DLog;
import com.common.base.log.RLog;
import com.photoeditor.BuildConfig;
import com.photoeditor.demo.model.preference.SpConstant;
import com.photoeditor.demo.model.preference.SpUtils;
import com.photoeditor.demo.util.TimeConstant;

import java.util.HashMap;
import java.util.Map;

/**
 * 作用及描述：软件更新，包括周期性自动检查更新和设置界面更新点击
 */
public class UpdateUtil {
    private static final String TAG = "UpdateUtil";

    public static final String IS_FORCE_UPDATE = "IS_FORCE_UPDATE";
    public static final String UPDATE_PKGNAME = "UPDATE_PKGNAME";
    public static final String UPDATE_TITLE = "UPDATE_TITLE";
    public static final String UPDATE_CONTENT = "UPDATE_CONTENT";
    public static final String UPDATE_URL = "UPDATE_URL";
    public static final String UPDATE_VERSION = "UPDATE_VERSION";
    public static final String UPDATE_FREQUENCY = "UPDATE_FREQUENCY";

    public static final String UPDATE_ENABLE_COUNTIRES = "UPDATE_ENABLE_COUNTIRES";
    public static final String UPDATE_ENABLE_VERSION = "UPDATE_ENABLE_VERSION";
    public static final String UPDATE_ENABLE_TIME = "UPDATE_ENABLE_TIME";
    public static final String UPDATE_ENABLE_LANGUAGES = "UPDATE_ENABLE_LANGUAGES";
    public static final String UPDATE_CONFIRM = "UPDATE_CONFIRM";
    public static final String UPDATE_CANCEL = "UPDATE_CANCEL";

    /**
     * 自动检测更新周期，单位：天
     */
    private final static int AUTO_CHECK_PERIOD_DAY = 0;
    // 自动检测间隔
    private final static long AUTO_CHECK_DELAYED = 8 * TimeConstant.ONE_HOUR;
    // 没网络延时4个小时再check
    private final static long NO_NET_CHECK_DELAYED = 4 * TimeConstant.ONE_HOUR;
    private final static String CHECK_UPDATE_URL = "******";
//            "http://conf.api.hk.goforandroid.com/api/v2/configurations" +
//            "?product_id=1140&config_names=version&client=eyAibGFuZyI6InpoIiwiY291bnRyeSI6InVzIiwiY2hhbm5lbCI" +
//            "6IjIwMCIsImN2ZXJzaW9uX25hbWUiOiIiLCJjdmVyc2lvbl9udW1iZXIiOiAxfQ==";


    private Activity mBaseContext;
    private UpdateDialogUtil mDialogUtil;

    private UpdateInfo mLastUpdateInfo = null;


    public UpdateUtil(Activity context) {
        mBaseContext = context;
        mDialogUtil = new UpdateDialogUtil(mBaseContext);
    }

    public boolean isUpdateDialogShowing() {
        return mDialogUtil != null && mDialogUtil.isUpdateDialogShowing();
    }

    public boolean isNeedForceUpdate() {
        return mLastUpdateInfo != null && mLastUpdateInfo.getForcibly();
    }

    private void setUpdateInfo(UpdateInfo updateInfo) {
        mLastUpdateInfo = updateInfo;
    }

    private boolean needCheck() {
        return !mDialogUtil.isUpdateDialogShowing();
    }

    /**
     * 检测是否需要显示升级弹窗，需要显示立即展示
     * @return 为true时，表示需要显示升级弹窗
     */
    public boolean checkUpdate() {
        UpdateInfo updateInfo = loadUpdateInfo();
        // 普通升级只显示指定次数，强制升级每次都需要显示
        if (updateInfo != null && updateInfo.version > BuildConfig.VERSION_CODE
                && (updateInfo.getForcibly() || (!updateInfo.getForcibly() && updateInfo.frequency > 0))) {
            this.mLastUpdateInfo = updateInfo;
            int currentVersion = getCurrentVersionCode();
            if (!this.mLastUpdateInfo.needUpdate(currentVersion)) {
                return false;
            }
            showDialog(DLG_TYPE_UPDATE);
            return true;
        }
        return false;
    }

    /**
     * 收到升级信息后保存到Preference
     */
    public static void saveUpdateInfo(UpdateInfo updateInfo) {
        String msgId = SpUtils.obtain().getString(SpConstant.LAST_UPDATE_INFO_ID);
        if (!TextUtils.isEmpty(msgId) && TextUtils.equals(msgId, updateInfo.msgId)) {
            DLog.d(TAG, "重复id");
            return;
        }
        SpUtils.obtain().save(SpConstant.LAST_UPDATE_INFO_ID, updateInfo.msgId);
        SpUtils.obtain().save(IS_FORCE_UPDATE, updateInfo.getForcibly());
        String pkgName = updateInfo.getStringInfo(UpdateInfo.TAG_PACKAGENAME,"");
        SpUtils.obtain().save(UPDATE_PKGNAME, pkgName);
        SpUtils.obtain().save(UPDATE_CONTENT, updateInfo.getContent());
        SpUtils.obtain().save(UPDATE_TITLE, updateInfo.getTitle());
        String url = updateInfo.getStringInfo(UpdateInfo.TAG_URL, "");
        SpUtils.obtain().save(UPDATE_URL, url);
        SpUtils.obtain().save(UPDATE_VERSION, updateInfo.getVersion());
        SpUtils.obtain().save(UPDATE_FREQUENCY, String.valueOf(updateInfo.frequency));
        SpUtils.obtain().save(UPDATE_CONFIRM, updateInfo.getStringInfo(UpdateInfo.TAG_CONFIRM, "ok"));
        SpUtils.obtain().save(UPDATE_CANCEL, updateInfo.getStringInfo(UpdateInfo.TAG_CANCEL, "cancel"));
    }

    private UpdateInfo loadUpdateInfo() {
        UpdateInfo ret;
        boolean isForce = SpUtils.obtain().getBoolean(IS_FORCE_UPDATE, false);
        ret = new UpdateUtil.UpdateInfo.Builder()
                .add(UpdateInfo.TAG_PACKAGENAME, SpUtils.obtain().getString(UPDATE_PKGNAME))
                .add(UpdateInfo.TAG_CONTENT, SpUtils.obtain().getString(UPDATE_CONTENT))
                .add(UpdateInfo.TAG_TITLE, SpUtils.obtain().getString(UPDATE_TITLE))
                .add(UpdateInfo.TAG_URL, SpUtils.obtain().getString(UPDATE_URL))
                .add(UpdateInfo.TAG_FORCIBLY, isForce ? "true" : "false")
                .add(UpdateInfo.TAG_FREQUENCY, SpUtils.obtain().getString(UPDATE_FREQUENCY))
                .add(UpdateInfo.TAG_MSGID, SpUtils.obtain().getString(SpConstant.LAST_UPDATE_INFO_ID))
                .add(UpdateInfo.TAG_CONFIRM, SpUtils.obtain().getString(UPDATE_CONFIRM))
                .add(UpdateInfo.TAG_CANCEL, SpUtils.obtain().getString(UPDATE_CANCEL))
                .build();
        ret.version = SpUtils.obtain().getInt(UPDATE_VERSION);
        return ret;
    }

    /**
     * 设置界面点击更新按钮直接检测更新
     */
//    private void checkUpdate() {
//        if (NetUtils.isNetWorkAvailable(mBaseContext)) {
//            showDialog(DLG_TYPE_UPDATING);
//            getServerVersionAsync(false);
//        } else {
//            showNoNetworkDialog();
//        }
//    }

    /**
     * 更新确认弹窗的更新按钮回调方法
     * 优先以Google Play 市场打开手电筒详情页，如果没有安装GP ,则以网址为数据进行匹配
     */
    public static void onUpdateClicked(UpdateInfo updateInfo, Context context) {
        if (updateInfo == null) {
            return;
        }
        //当用户点击update或已展示三次后，不再进行展示
        SpUtils.obtain().save(UPDATE_FREQUENCY, String.valueOf(0));
        String url = updateInfo.getStringInfo(UpdateInfo.TAG_URL, "");
        if (!TextUtils.isEmpty(url)) {
            try {
                context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            String appPackageName = updateInfo.getStringInfo(UpdateInfo.TAG_PACKAGENAME,"");
            if(TextUtils.isEmpty(appPackageName)) {
                appPackageName = ComponentContext.getPackageName();
            }
            try {
                Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage("com.android.vending");
                ComponentName comp = new ComponentName("com.android.vending", "com.google.android.finsky.activities.LaunchUrlHandlerActivity");
                launchIntent.setComponent(comp);
                launchIntent.setData(Uri.parse("market://details?id=" + appPackageName));
                context.startActivity(launchIntent);
            } catch (Exception ex) {
                RLog.d(TAG, "Google Play client is not found!");
                try {
                    context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://play.google.com/store/apps/details?id=" + appPackageName)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 获取自上次检查更新至今的天数
     */
    private long getDayFromLastCheckUpdate() {
        long lastUpdateTime = SpUtils.obtain().getLong(SpConstant.LAST_UPDATE_MILLISECONDS, 0L);
        if (lastUpdateTime == 0L) {
            //没有上一次记录，返回零，因为第一次启动App时，不检查更新，但写入这一次的时间，以保证下一次自动更新自动运行
            setUpdateDataFlag();
            return lastUpdateTime;
        }
        long currentTime = System.currentTimeMillis();
        long diff = Math.abs(currentTime - lastUpdateTime);
        return diff / TimeConstant.ONE_DAY;
    }

    /**
     * 向偏好设置里写入当天更新日期
     */
    private void setUpdateDataFlag() {
        long currentTimes = System.currentTimeMillis();
        SpUtils.obtain().save(SpConstant.LAST_UPDATE_MILLISECONDS, currentTimes);
    }

    /**
     * 从服务器获取当前最新版本
     */
//    private void getServerVersionAsync(boolean isAutoUpdate) {
//        VersionCodeTextResponse textResponse = new VersionCodeTextResponse();
//        if (isAutoUpdate) {
//            textResponse.setShowNoUpdateDialog(false);
//        }
//        mHttpClient.get(mBaseContext, CHECK_UPDATE_URL, textResponse);
//    }

    private void updateVersioin(boolean mIsShowNoUpdateDialog) {
        if(mLastUpdateInfo == null) {
            return;
        }
        int currentVersion = getCurrentVersionCode();
        if (mLastUpdateInfo.getVersion() > currentVersion) {
            showDialog(DLG_TYPE_UPDATE);
        } else if (mLastUpdateInfo.getVersion() == currentVersion) {
            if (mIsShowNoUpdateDialog) {
                showDialog(DLG_TYPE_NO_UPDATE);
            }
        } else {
            //服务器版本低于当前版本，是否做出错处理？
        }
    }

    /**
     * 获取当前本地版本号
     *
     * @return 本地APP版本号，主要用于比较升级
     */
    private int getCurrentVersionCode() {
        if (mBaseContext == null) {
            return -1;
        }
        PackageManager manager;
        PackageInfo info;
        manager = mBaseContext.getPackageManager();
        try {
            info = manager.getPackageInfo(mBaseContext.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException | RuntimeException e) {
            e.printStackTrace();
            return -1;
        }
        return info.versionCode;
    }

    /*
    {
        "version": "100", // versionCode
        "url":  "", // 如果为空，则用默认包名去gp上下载，先市场，再网页
        "packagename": "", // 包名，如果为空，默认以当前包名
        "forcibly": "false", // 是否强制更新
        "silent": "false", // 是否静默下载
        "id": "201701021200",// 当前时间，用来区分重复消息
        "frequency": "3",// 显示次数
    }
     */
    public static class UpdateInfo {
        private Map<String, String> mInfos;
        private int version;
        private String msgId;
        private int frequency;

        public static class Builder {
            UpdateInfo mUpdateInfo;
            public Builder() {
                mUpdateInfo = new UpdateInfo();
                mUpdateInfo.mInfos = new HashMap<>();
            }

            public Builder add(Map<String, String> infos) {
                mUpdateInfo.mInfos.putAll(infos);
                return this;
            }

            public Builder add(String key, String value) {
                mUpdateInfo.mInfos.put(key, value);
                return this;
            }

            public UpdateInfo build() {
                mUpdateInfo.version = mUpdateInfo.getIntValue(TAG_VERSION, 0);
                mUpdateInfo.msgId = mUpdateInfo.getStringInfo(TAG_MSGID, "");
                mUpdateInfo.frequency = mUpdateInfo.getIntValue(TAG_FREQUENCY, 1);
                return mUpdateInfo;
            }
        }

        public String getStringInfo(String key, String defaultValue) {
            if (!mInfos.containsKey(key)) {
                return defaultValue;
            } else {
                if (!TextUtils.isEmpty(mInfos.get(key))) {
                    return mInfos.get(key).trim();
                } else {
                    return "";
                }
            }
//            return mInfos.containsKey(key) ? mInfos.get(key).trim() : defaultValue;
        }

        public boolean getBooleanInfo(String key, boolean defaultValue) {
            if(mInfos.containsKey(key)) {
                String value = mInfos.get(key);
                if(TextUtils.equals(value, "true")) {
                    return true;
                } else if(TextUtils.equals(value, "false")) {
                    return false;
                }
            }
            return defaultValue;
        }

        public int getIntValue(String key, int defaultValue) {
            if(mInfos.containsKey(key)) {
                String value = mInfos.get(key);
                try {
                    return Integer.parseInt(value);
                } catch (NumberFormatException e) {
                }
            }
            return defaultValue;
        }

        public int getVersion() {
            return version;
        }

        public String getTitle() {
            return getStringInfo(TAG_TITLE, "");
        }

        public String getContent() {
            return getStringInfo(TAG_CONTENT, "");
        }

        public boolean getForcibly() {
            return getBooleanInfo(TAG_FORCIBLY, false);
        }

        public String getMsgId() {
            return msgId;
        }


        public static final String TAG_TITLE = "title";
        public static final String TAG_CONTENT = "content";
        public static final String TAG_VERSION = "version";
        public static final String TAG_URL = "url";
        public static final String TAG_PACKAGENAME = "packagename";
        public static final String TAG_FORCIBLY = "forcibly";
        public static final String TAG_SILENT = "silent";
        public static final String TAG_MSGID = "msgid";
        public static final String TAG_FREQUENCY = "frequency";
        public static final String TAG_ENABLE_COUNTRIES = "enableCountries";
        public static final String TAG_ENABLE_VERSION = "enableVersion";
        public static final String TAG_ENABLE_TIME = "enableTime";
        public static final String TAG_ENABLE_LANGUAGES = "enableLanguages";
        public static final String TAG_CONFIRM = "confirm";
        public static final String TAG_CANCEL = "cancel";

        public boolean needUpdate(int oldVersion) {
            return oldVersion < version;
        }

        public boolean isRepeatInfo(String msgId) {
            return !TextUtils.isEmpty(msgId) && TextUtils.equals(this.msgId, msgId);
        }
    }

//    private static class GPVersionCodeTextResponse extends TextHttpResponseHandler {
//        private boolean mIsShowNoUpdateDialog;
//
//        public GPVersionCodeTextResponse() {
//            mIsShowNoUpdateDialog = true;
//        }
//
//        public void setShowNoUpdateDialog(boolean showNoUpdateDialog) {
//            mIsShowNoUpdateDialog = showNoUpdateDialog;
//        }
//
//        @Override
//        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
//            if (BuildConfig.DEBUG) {
//                LogUtils.d(UpdateUtil.TAG, "Version code request failed!");
//            }
//        }
//
//        @Override
//        public void onSuccess(int statusCode, Header[] headers, String responseString) {
//            if (!TextUtils.isEmpty(responseString)) {
//                return;
//            }
//            String newVersion = "";
//            Pattern p = Pattern.compile("\"softwareVersion\"\\W*([\\d\\.]+)");
//            Matcher matcher = p.matcher(responseString);
//            if (matcher.find()) {
//                newVersion = matcher.group(1);
//            }
//            UpdateInfo updateInfo = new UpdateInfo.Builder().add(UpdateInfo.TAG_VERSION, newVersion).build();
//            UpdateUtil.getInstance(null).setUpdateInfo(updateInfo);
//
//            UpdateUtil.getInstance(null).setUpdateDataFlag();
//            UpdateUtil.getInstance(null).updateVersioin(mIsShowNoUpdateDialog);
//        }
//    }

//    /**
//     * 请求服务器最新版本回调
//     *
//     * @see AsyncHttpClient
//     * @see TextHttpResponseHandler
//     */
//    private static class VersionCodeTextResponse extends JsonHttpResponseHandler {
//        private boolean mIsShowNoUpdateDialog;
//
//        public VersionCodeTextResponse() {
//            mIsShowNoUpdateDialog = true;
//        }
//
//        public void setShowNoUpdateDialog(boolean showNoUpdateDialog) {
//            mIsShowNoUpdateDialog = showNoUpdateDialog;
//        }
//
//        @Override
//        public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
//            if (BuildConfig.DEBUG) {
//                LogUtils.d(UpdateUtil.TAG, "Version code request failed!");
//            }
//        }
//
//        @Override
//        public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
//            super.onSuccess(statusCode, headers, response);
//            if (BuildConfig.DEBUG) {
//                LogUtils.d(UpdateUtil.TAG, "Version code request success!");
//            }
//
//            UpdateInfo.Builder builder = new UpdateInfo.Builder();
//
//            try {
//                builder.add(UpdateInfo.TAG_CONTENT, response.optString(UpdateInfo.TAG_CONTENT));
//                builder.add(UpdateInfo.TAG_VERSION, response.optString(UpdateInfo.TAG_VERSION));
//                builder.add(UpdateInfo.TAG_URL, response.optString(UpdateInfo.TAG_URL));
//                builder.add(UpdateInfo.TAG_PACKAGENAME, response.optString(UpdateInfo.TAG_PACKAGENAME));
//                builder.add(UpdateInfo.TAG_FORCIBLY, response.optString(UpdateInfo.TAG_FORCIBLY));
//                builder.add(UpdateInfo.TAG_SILENT, response.optString(UpdateInfo.TAG_SILENT));
//                builder.add(UpdateInfo.TAG_MSGID, response.optString(UpdateInfo.TAG_MSGID));
//            } catch (Exception e) {
//            }
//
//            UpdateInfo updateInfo = builder.build();
//            UpdateUtil.getInstance(null).setUpdateInfo(updateInfo);
//
//            UpdateUtil.getInstance(null).setUpdateDataFlag();
//            UpdateUtil.getInstance(null).updateVersioin(mIsShowNoUpdateDialog);
//        }
//
//        @Override
//        public void onSuccess(int statusCode, Header[] headers, String responseString) {
//            super.onSuccess(statusCode, headers, responseString);
//        }
//
//        @Override
//        public void onFinish() {
//            super.onFinish();
//            UpdateUtil.getInstance(null).setUpdateInfo(null);
//        }
//    }

    private boolean needShowDialog() {
        // 需要判断：
        // 如果是在桌面，则直接显示
        // 如果是在程序内，并且关闭了手电筒，则直接显示
        if(BaseApplication.isBackground()) {
            return false;
        }

        return true;
    }

    private final int DLG_TYPE_NO_UPDATE = 0;
    private final int DLG_TYPE_UPDATE = 1;
    private final int DLG_TYPE_UPDATING = 2;
    private final int DLG_TYPE_NO_NETWORK = 3;

    private void showDialog(int type) {
        switch (type) {
            case DLG_TYPE_NO_UPDATE:
                mDialogUtil.showNoUpdateDialog();
                break;
            case DLG_TYPE_UPDATE:
                SpUtils.obtain().save(SpConstant.LAST_UPDATE_INFO_ID, mLastUpdateInfo.getMsgId());
                SpUtils.obtain().save(UPDATE_FREQUENCY, String.valueOf(mLastUpdateInfo.frequency - 1));
                mDialogUtil.showUpdateDialog(mLastUpdateInfo.getTitle(), mLastUpdateInfo.getContent(), mLastUpdateInfo);
                break;
            case DLG_TYPE_NO_NETWORK:
                mDialogUtil.showNoNetworkDialog();
                break;
            default:
                break;
        }
    }


}
